package com.th.supcom.pds.impl.service.internal.phamapply;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import net.carefx.fc.framework.db.manager.GetSequenceHelper;
import net.carefx.fc.framework.web.gwt.util.FcUtils;
import net.carefx.framework.exception.BusinessException;
import net.carefx.framework.translate.TranslatorManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.th.supcom.pds.domain.pojo.DeptVsDispensary;
import com.th.supcom.pds.domain.pojo.InpPhamApplyDetail;
import com.th.supcom.pds.domain.pojo.InpPhamApplyMaster;
import com.th.supcom.pds.domain.pojo.InpPhamApplyPatInfo;
import com.th.supcom.pds.domain.vo.InpPhamApplyDetailVO;
import com.th.supcom.pds.domain.vo.PrescSearchDTOVO;
import com.th.supcom.pds.domain.vo.PtsPaiAdtLogVo;
import com.th.supcom.pds.impl.common.PdsConstants;
import com.th.supcom.pds.impl.common.enums.InFlag;
import com.th.supcom.pds.impl.common.enums.InpChargeIndicator;
import com.th.supcom.pds.impl.common.enums.InpDispenseIndicator;
import com.th.supcom.pds.impl.common.enums.InpWithDrawType;
import com.th.supcom.pds.impl.common.enums.IsCancel;
import com.th.supcom.pds.impl.common.enums.PhamReturnIndicator;
import com.th.supcom.pds.impl.common.enums.PhamReturnIndicatorConfig;
import com.th.supcom.pds.impl.common.utils.ExceptionThrowHelper;
import com.th.supcom.pds.internal.api.phamapply.DeptVsDispensaryBasicService;
import com.th.supcom.pds.internal.api.phamapply.InPharmacyReturnService;
import com.th.supcom.pds.internal.api.phamapply.InpPhamApplyDetailBasicService;
import com.th.supcom.pds.internal.api.phamapply.InpPhamApplyMasterBasicService;
import com.th.supcom.pds.internal.api.phamapply.NurseReturnService;
import com.th.supcom.pds.medicare.api.AdapterBMSChargeService;
import com.th.supcom.pds.medicare.api.AdapterPTSPatientInfoService;

/**
 * @author yzhang
 */
/**
 *
 */
public class NurseReturnServiceImpl implements NurseReturnService
{
    /** 日志记录器. */
    public static final Logger s_logger = LoggerFactory.getLogger (InPharmacyReturnService.class);
    private AdapterPTSPatientInfoService m_adapterPTSPatientInfoService;
    private AdapterBMSChargeService m_adapterBMSChargeService;
    private InpPhamApplyDetailBasicService m_inpPhamApplyDetailBasicService;
    private InpPhamApplyMasterBasicService m_inpPhamApplyMasterBasicService;
    private TranslatorManager m_translatorManager;
    private GetSequenceHelper m_getSequenceHelper;
    private DeptVsDispensaryBasicService m_deptVsDispensaryBasicService;
    public static final String TAB_INP_PHAM_APPLY_MASTER = "INP_PHAM_APPLY_MASTER";

    /**
     * 查询该患者所有就诊记录
     * 
     * @param patientId
     * @return
     */
    @Override
    public List <InpPhamApplyPatInfo> findPatientInfoByPatient (Long patientId)
    {
        List <InpPhamApplyPatInfo> paiVisits1 = null;
        ExceptionThrowHelper.throwIllegalArgumentException (null == patientId, "通过患者ID查询患者纪录时，患者ID不能为空");
        paiVisits1 = m_adapterPTSPatientInfoService.findPatiInfoByPatientId (patientId);
        ExceptionThrowHelper.throwBusinessException (paiVisits1.isEmpty (), "患者ID不存在，请重新输入！");
        paiVisits1 = m_adapterBMSChargeService.obtainPatAvailablePrepayment (paiVisits1);
        ExceptionThrowHelper.throwBusinessException (paiVisits1.isEmpty (), "患者ID输入错误，请重新输入！" + PdsConstants.DEFALUT_HTML_WRAP);
        paiVisits1 = m_translatorManager.translate (paiVisits1);
        // 最后一次就诊为未出院，设置出院时间为当前时间
        if (paiVisits1.get (0).getInFlag ().equals (InFlag.Unchecked.getEnumCode ()))
        {
            paiVisits1.get (0).setDischargeDeptDate (FcUtils.getCurrentServerDateTimeForServer ());
        }
        return paiVisits1;
    }

    /**
     * 通过患者住院流水号查询本次住院所有转科记录
     * 
     * @param paiVisitId
     * @return
     */
    public List <PtsPaiAdtLogVo> findPaiAdtLogVosById (Long paiVisitId)
    {
        List <PtsPaiAdtLogVo> ptsPaiAdtLogVos = m_adapterPTSPatientInfoService.findPaiAdtLogVosById (paiVisitId);
        return ptsPaiAdtLogVos;
    }

    /**
     * 根据查询条件查询
     * 
     * @param prescSearchDTOVO 查询条件
     * @return
     */
    public List <InpPhamApplyDetail> findChargeItemByExample (PrescSearchDTOVO prescSearchDTOVO)
    {
        ExceptionThrowHelper.throwIllegalArgumentException (prescSearchDTOVO.getPatientId () == null, "调用计费接口查询费用明细时，患者ID为空");
        List <InpPhamApplyDetail> inpPhamApplyDetails = m_adapterBMSChargeService.findChargeItemByExample (prescSearchDTOVO);

        for (InpPhamApplyDetail inpPhamApplyDetail : inpPhamApplyDetails)
        {
            inpPhamApplyDetail.setApplyUnit (m_inpPhamApplyDetailBasicService.findPhamUnitByPhamStdCode (inpPhamApplyDetail.getPhamStdCode ()));
            DeptVsDispensary deptVsDispensary = new DeptVsDispensary ();
            deptVsDispensary.setDeptCode (prescSearchDTOVO.getNurseUnit ());
            deptVsDispensary.setDispensary (inpPhamApplyDetail.getApplyDispensary ());
            List <DeptVsDispensary> deptVsDispensarys = m_deptVsDispensaryBasicService.findDeptVsDispensaryListByExample (deptVsDispensary);

            if (!deptVsDispensarys.isEmpty ())
            {
                inpPhamApplyDetail.setWithdrawType (deptVsDispensarys.get (0).getWithdrawType () == null ? InpWithDrawType.ReturnWithoutDrug.getEnumCode ()
                                                                                                        : deptVsDispensarys.get (0)
                                                                                                                           .getWithdrawType ());
                inpPhamApplyDetail.setWithdrawConfig (deptVsDispensarys.get (0).getWithdrawType () == null ? InpWithDrawType.ReturnWithoutDrug.getEnumCode ()
                                                                                                          : deptVsDispensarys.get (0)
                                                                                                                             .getWithdrawType ());
                inpPhamApplyDetail.setPhamReturnIndicatorConfig (deptVsDispensarys.get (0).getIsReturn () == null ? PhamReturnIndicatorConfig.NoReturn.getEnumCode ()
                                                                                                                 : deptVsDispensarys.get (0)
                                                                                                                                    .getIsReturn ());
            }
            // 查询药品不可退药品标志
            if (!CollectionUtils.isEmpty (m_inpPhamApplyDetailBasicService.getDrugReturnIndicator (inpPhamApplyDetail)))
            {
                inpPhamApplyDetail.setPhamReturnIndicator (PhamReturnIndicator.NoReturn.getEnumCode ());
            }
        }
        inpPhamApplyDetails = m_translatorManager.translate (inpPhamApplyDetails);
        return inpPhamApplyDetails;
    }

    @Override
    public List <String> generateDrugReturn (List <InpPhamApplyDetail> applyDetails, String nurseUnit, String operator,
                                             InpPhamApplyPatInfo inpPhamApplyPatInfo)
    {

        return generateBill (applyDetails, nurseUnit, operator, inpPhamApplyPatInfo);

    }

    /**
     * 查询所退记录的申请单号是否已经存在于已经生成的电子退药单(且是药房未处理状态) 存在:作废之前的电子退药单，生成电子退药单
     * 不存在：直接生成电子退药单
     * 
     * @param applyDetails
     * @return
     */
    private void judgeExist (List <InpPhamApplyDetail> applyDetails)
    {
        InpPhamApplyMaster inpMasterForUpdate;
        for (InpPhamApplyDetail inpPhamApplyDetail : applyDetails)
        {
            InpPhamApplyDetail inpDetail = new InpPhamApplyDetail ();
            inpDetail.setWithdrawApplyNo (inpPhamApplyDetail.getWithdrawApplyNo ());
            inpDetail.setChargeIndicator (InpChargeIndicator.ReturnApplied.getEnumCode ());
            inpDetail.setDispenseIndicator (InpDispenseIndicator.HasReturnApplyed.getEnumCode ());
            List <InpPhamApplyDetailVO> details = m_inpPhamApplyDetailBasicService.findInpPhamApplyDetailListByExample (inpDetail);
            if (!CollectionUtils.isEmpty (details))
            {
                inpMasterForUpdate = new InpPhamApplyMaster ();
                inpMasterForUpdate.setApplyNo (details.get (0).getApplyNo ());
                inpMasterForUpdate.setIsCancel (IsCancel.YES.getEnumCode ());
                m_inpPhamApplyMasterBasicService.modifyInpPhamApplyMasterByExample (inpMasterForUpdate);
            }
        }
    }

    /**
     * @param applyDetails退药申请明细
     * @param operator 操作人
     */
    private List <String> generateBill (List <InpPhamApplyDetail> applyDetails, String nurseUnit, String operator,
                                        InpPhamApplyPatInfo inpPhamApplyPatInfo)
    {
        // 查询所退记录的申请单号是否已经存在于已经生成的电子退药单(且是药房未处理状态)
        // 存在:作废之前的电子退药单，生成电子退药单 .不存在：直接生成电子退药单
        judgeExist (applyDetails);
        // 按所有规则分组后生成的申请单号
        List <String> allApplyNo = new ArrayList <String> ();
        // 带药退药 按执行科室(药房)分组后的List<String>
        List <String> withOutDrugApplyDispensaryList = new ArrayList <String> ();
        // 不带药带药退药 按执行科室(药房)分组后的List<String>
        List <String> withDrugApplyDispensaryList = new ArrayList <String> ();
        // 带药退药明细
        List <InpPhamApplyDetail> withDrugApplyDetails = new ArrayList <InpPhamApplyDetail> ();
        // 不带药退药明细
        List <InpPhamApplyDetail> withOutDrugApplyDetails = new ArrayList <InpPhamApplyDetail> ();
        // 根据不带药，带药分组
        for (InpPhamApplyDetail inpPhamApplyDetail : applyDetails)
        {
            if (InpWithDrawType.ReturnWithDrug.getEnumCode ().equals (inpPhamApplyDetail.getWithdrawType ()))
            {
                withDrugApplyDetails.add (inpPhamApplyDetail);
            }
            else
            {
                withOutDrugApplyDetails.add (inpPhamApplyDetail);
            }
        }
        // 按執行科室(药房)分组
        Map <String, List <InpPhamApplyDetail>> withDrugApplyDetailsmap = PhamApplyConvertUtils.convertListToMapByApplyDispensary (withDrugApplyDetails,
                                                                                                                                   withDrugApplyDispensaryList);
        Map <String, List <InpPhamApplyDetail>> withOutDrugApplyDetailsmap = PhamApplyConvertUtils.convertListToMapByApplyDispensary (withOutDrugApplyDetails,
                                                                                                                                      withOutDrugApplyDispensaryList);
        try
        {
            // 带药退药电子单生成
            for (int i = 0; i < withDrugApplyDispensaryList.size (); i++)
            {
                String applyNo = generateApplyMaster (nurseUnit, operator);
                List <InpPhamApplyDetail> applyDetailList = withDrugApplyDetailsmap.get (withDrugApplyDispensaryList.get (i));
                generateApplyDetail (applyDetailList, nurseUnit, inpPhamApplyPatInfo, applyNo);
                allApplyNo.add (applyNo);
            }
            // 不带药退药电子单生成
            for (int i = 0; i < withOutDrugApplyDispensaryList.size (); i++)
            {
                String applyNo = generateApplyMaster (nurseUnit, operator);
                List <InpPhamApplyDetail> applyDetailList = withOutDrugApplyDetailsmap.get (withOutDrugApplyDispensaryList.get (i));
                generateApplyDetail (applyDetailList, nurseUnit, inpPhamApplyPatInfo, applyNo);
                allApplyNo.add (applyNo);
            }
            return allApplyNo;
        }
        catch (Exception e)
        {
            s_logger.error ("生成电子退药单出现异常！", e);
            throw new BusinessException ("生成电子退药单失败！请联系计算机中心！", e);
        }

    }

    /**
     * 生成退药请领主表
     */
    private String generateApplyMaster (String nurseUnit, String operator)
    {
        String applyNo = PhamApplyStaticMethod.generateApplyNo (m_getSequenceHelper.getNextSequenceId (TAB_INP_PHAM_APPLY_MASTER),
                                                                operator);
        InpPhamApplyMaster inpPhamApplyMaster = new InpPhamApplyMaster ();
        inpPhamApplyMaster.setNurseUnit (nurseUnit);
        inpPhamApplyMaster.setIsCancel (IsCancel.NO.getEnumCode ());
        inpPhamApplyMaster.setApplyBy (operator);
        inpPhamApplyMaster.setApplyDatetime (FcUtils.getCurrentServerDateTimeForServer ());
        inpPhamApplyMaster.setApplyNo (applyNo);
        m_inpPhamApplyMasterBasicService.addInpPhamApplyMaster (inpPhamApplyMaster);
        return applyNo;
    }

    /**
     * 生成退药请领明细
     */

    private void generateApplyDetail (List <InpPhamApplyDetail> applyDetails, String nurseUnit,
                                      InpPhamApplyPatInfo inpPhamApplyPatInfo, String applyNo)

    {
        for (InpPhamApplyDetail applyDetail : applyDetails)
        {
            applyDetail.setApplyNo (applyNo);
            applyDetail.setPaiVisitId (inpPhamApplyPatInfo.getPaiVisitId ());
            applyDetail.setNurseUnit (nurseUnit);
            applyDetail.setWard (applyDetail.getWard ());
            applyDetail.setBedNo (inpPhamApplyPatInfo.getBedNo ());
            applyDetail.setApplyDispensary (applyDetail.getApplyDispensary ());
            applyDetail.setExecDispensary (applyDetail.getApplyDispensary ());
            applyDetail.setPhamStdCode (applyDetail.getPhamStdCode ());
            applyDetail.setPhamName (applyDetail.getPhamName ());
            applyDetail.setPhamSpec (applyDetail.getPhamSpec ());
            applyDetail.setApplyUnit (applyDetail.getApplyUnit ());
            applyDetail.setApplyAmount (-applyDetail.getWithdrawAmount ());
            applyDetail.setChargeIndicator (InpChargeIndicator.ReturnApplied.getEnumCode ());
            applyDetail.setDispenseIndicator (InpDispenseIndicator.HasReturnApplyed.getEnumCode ());
            applyDetail.setWithdrawApplyNo (applyDetail.getWithdrawApplyNo ());
            if (InpWithDrawType.ReturnWithoutDrug.getEnumCode ().equals (applyDetail.getWithdrawType ()))
            {
                applyDetail.setOffsetAmount (Math.abs (applyDetail.getApplyAmount ().longValue ()));
            }
        }
        m_inpPhamApplyDetailBasicService.addInpPhamApplyDetailList (applyDetails);
    }

    public void setAdapterPTSPatientInfoService (AdapterPTSPatientInfoService adapterPTSPatientInfoService)
    {
        m_adapterPTSPatientInfoService = adapterPTSPatientInfoService;
    }

    public void setAdapterBMSChargeService (AdapterBMSChargeService adapterBMSChargeService)
    {
        m_adapterBMSChargeService = adapterBMSChargeService;
    }

    public void setInpPhamApplyDetailBasicService (InpPhamApplyDetailBasicService inpPhamApplyDetailBasicService)
    {
        m_inpPhamApplyDetailBasicService = inpPhamApplyDetailBasicService;
    }

    public void setInpPhamApplyMasterBasicService (InpPhamApplyMasterBasicService inpPhamApplyMasterBasicService)
    {
        m_inpPhamApplyMasterBasicService = inpPhamApplyMasterBasicService;
    }

    public void setTranslatorManager (TranslatorManager translatorManager)
    {
        m_translatorManager = translatorManager;
    }

    public void setDeptVsDispensaryBasicService (DeptVsDispensaryBasicService deptVsDispensaryBasicService)
    {
        m_deptVsDispensaryBasicService = deptVsDispensaryBasicService;
    }

    @Override
    public InpPhamApplyPatInfo getPatInfoByBedNo (String nurseUnit, String bedNo)
    {
        s_logger.info ("调用getPatInfoByBedNo参数 ：nurseUnit:{},bedNo:{}", new Object[]
        { nurseUnit, bedNo });
        ExceptionThrowHelper.throwIllegalArgumentException (null == nurseUnit, "通过床号、护理单元查询患者数据时，护理单元为空!");
        ExceptionThrowHelper.throwIllegalArgumentException (null == bedNo, "通过床号、护理单元查询患者数据时，床号为空!");
        List <InpPhamApplyPatInfo> applyPatInfos = m_adapterPTSPatientInfoService.obtainPatBasicInfo (nurseUnit);
        List <InpPhamApplyPatInfo> applyPatInfoList = new ArrayList <InpPhamApplyPatInfo> ();
        for (InpPhamApplyPatInfo inpPhamApplyPatInfo : applyPatInfos)
        {
            if (bedNo.equals (inpPhamApplyPatInfo.getBedNo ()))
            {
                applyPatInfoList.add (inpPhamApplyPatInfo);
            }
        }
        ExceptionThrowHelper.throwBusinessException (applyPatInfoList.isEmpty (), "找不到患者信息，请检查床号是否输入正确！");
        // 查询预交金
        applyPatInfoList = m_adapterBMSChargeService.obtainPatAvailablePrepayment (applyPatInfoList);
        return applyPatInfoList.get (0);
    }

    public void setGetSequenceHelper (GetSequenceHelper getSequenceHelper)
    {
        m_getSequenceHelper = getSequenceHelper;
    }

    /** 公司版权信息. */
    public static final String copyright = "Copyright 2014, XuNuo Corporation";

    /** 提交路径. */
    public static final String SCC_BRANCH = "$URL$";

    /** 提交日期. */
    public static final String SCC_LAST_MODIFICATION_DATE = "$Date$";

    /** 最终修改人员. */
    public static final String SCC_LAST_MODIFIER_NAME = "$Author$";

    /** 最终版本号. */
    public static final String SCC_REVISION = "$Revision$";
}
